<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html lang="en-US">
<head>
    <meta charset="utf-8">


    <link href="/assets/css/all.css" rel="stylesheet" type="text/css">
    <script async src="/assets/js/all.js"></script>


    <script type="text/x-mathjax-config">
      MathJax.Hub.Config({tex2jax: {inlineMath: [['«', '»']]}});
      MathJax.Hub.config.tex2jax.skipTags = ["script", "noscript", "style", "textarea", "annotation", "annotation-xml"];

    </script>
    <script async src='https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.2/MathJax.js?config=TeX-AMS_HTML'></script>
    <!-- Google Analytics -->
    <script>
        window.ga = window.ga || function () {
            (ga.q = ga.q || []).push(arguments)
        };
        ga.l = +new Date;
        ga('create', 'UA-58002512-1', 'auto');
        ga('set', 'anonymizeIp', true);
        ga('send', 'pageview');
    </script>
    <script async src='https://www.google-analytics.com/analytics.js'></script>
    <!-- End Google Analytics -->

    <title>Nim by Example - For Loops & Iterators</title>

    <meta content="nanoc 4.9.9" name="generator">
    <meta content="colorful" http-equiv="Default-Style">
    <meta content="width=device-width, initial-scale=1" name=viewport>
</head>
<body>

<div id="sidebar">
    <div class="abs-hamburger">
        <div class="nav-toggle" onclick="sidebarClick();"><span></span></div>
    </div>
    <nav>
        <ul>
            <li><a href="/getting_started/">Getting Started</a></li>
            <li><a href="/hello_world/">Hello World</a></li>
            <li><a href="/comments/">Comments</a></li>
            <li><a href="/variables/">Variables</a>
                <ul>
                    <li><a href="/variables/result/">Result</a></li>
                    <li><a href="/variables/type_casting_inference/">Type Casting and Inference</a></li>
                </ul>
            </li>
            <li><a href="/if_else_while/">If, Else, While</a></li>
            <li><a href="/case/">Case Statements</a></li>
            <li><a href="/for_iterators/">For Loops &amp; Iterators</a></li>
            <li><a href="/procs/">Procs</a></li>
            <li><a href="/procvars/">First Class Functions</a></li>
            <li><a href="/block/">Blocks</a></li>
            <li><a href="/primitives/">Primitive Types</a></li>
            <li><a href="/types/">Type Aliases</a></li>
            <li><a href="/types/objects/">Object Types</a></li>
            <li><a href="/types/enums/">Enum Types</a></li>
            <li><a href="/types/distinct/">Distinct Types</a></li>
            <li><a href="/strings/">Strings</a></li>
            <li><a href="/arrays/">Arrays</a></li>
            <li><a href="/seqs/">Seqs</a></li>
            <li><a href="/bitsets/">Bitsets</a></li>
            <li><a href="/files/">Files</a></li>
            <li><a href="/json/">JSON</a></li>
            <li><a href="/varargs/">Varargs</a></li>
            <li><a href="/oop/">Object Oriented Programming</a></li>
            <li><a href="/macros/">Macros</a></li>
        </ul>


    </nav>
</div>

<article>
    <h1 id="for-loops--iterators">For Loops &amp; Iterators</h1>

    <p>Nim has first class iterators and syntax to use them, for loops. The <code>continue</code> and <code>break</code>
        keywords also work inside of for loops. There are two kinds of iterator, and two special methods that for loops
        work with.</p>

    <h2 id="items-and-pairs">
        <code>items</code> and <code>pairs</code>
    </h2>

    <p>When iterating over an object with one item, Nim will call an iterator called <code>items</code> with the first
        parameter the type you want to iterate over. The same thing happens when iterating with two items, but in that
        case, the <code>pairs</code> iterator is called.</p>

    <pre><code class="language-nimrod"><span class="k">type</span>
  <span class="n">CustomRange</span> <span class="o">=</span> <span class="k">object</span>
    <span class="n">low</span><span class="p">:</span> <span class="kt">int</span>
    <span class="n">high</span><span class="p">:</span> <span class="kt">int</span>

<span class="k">iterator</span> <span class="n">items</span><span class="p">(</span><span class="kt">range</span><span
                class="p">:</span> <span class="n">CustomRange</span><span class="p">):</span> <span
                class="kt">int</span> <span class="o">=</span>
  <span class="kd">var</span> <span class="n">i</span> <span class="o">=</span> <span class="kt">range</span><span
                class="p">.</span><span class="n">low</span>
  <span class="k">while</span> <span class="n">i</span> <span class="o">&lt;=</span> <span class="kt">range</span><span
                class="p">.</span><span class="n">high</span><span class="p">:</span>
    <span class="k">yield</span> <span class="n">i</span>
    <span class="n">inc</span> <span class="n">i</span>

<span class="k">iterator</span> <span class="n">pairs</span><span class="p">(</span><span class="kt">range</span><span
                class="p">:</span> <span class="n">CustomRange</span><span class="p">):</span> <span
                class="k">tuple</span><span class="o">[</span><span class="n">a</span><span class="p">:</span> <span
                class="kt">int</span><span class="p">,</span> <span class="n">b</span><span class="p">:</span> <span
                class="kt">char</span><span class="o">]</span> <span class="o">=</span>
  <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="kt">range</span><span
                class="p">:</span>  <span class="c"># uses CustomRange.items</span>
    <span class="k">yield</span> <span class="p">(</span><span class="n">i</span><span class="p">,</span> <span
                class="kt">char</span><span class="p">(</span><span class="n">i</span> <span class="o">+</span> <span
                class="n">ord</span><span class="p">(</span><span class="sc">'a'</span><span class="p">)))</span>

<span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">c</span> <span
                class="ow">in</span> <span class="n">CustomRange</span><span class="p">(</span><span
                class="n">low</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span> <span
                class="n">high</span><span class="p">:</span> <span class="mi">3</span><span class="p">):</span>
  <span class="n">echo</span> <span class="n">c</span></code></pre>
    <pre><code class="language-console"><span class="gp">$</span> nim c -r items_pair.nim
<span class="go">b</span>
<span class="go">c</span>
<span class="go">d</span></code></pre>

    <h2 id="operators">Operators</h2>
    <p>Iterators can also be operators <a href="../procs#operators">in the standard way</a>, with the name enclosed in
        backticks. For example, the standard library defines the slice iterator, which allows iterating through <a
                href="../types/enums#ordinals">ordinal types</a>.</p>

    <pre><code class="language-nimrod"><span class="c"># Give it a different name to avoid conflict</span>
<span class="k">iterator</span> <span class="p">`...`</span><span class="o">*[</span><span class="n">T</span><span
                class="o">]</span><span class="p">(</span><span class="n">a</span><span class="p">:</span> <span
                class="n">T</span><span class="p">,</span> <span class="n">b</span><span class="p">:</span> <span
                class="n">T</span><span class="p">):</span> <span class="n">T</span> <span class="o">=</span>
  <span class="kd">var</span> <span class="n">res</span><span class="p">:</span> <span class="n">T</span> <span
                class="o">=</span> <span class="n">T</span><span class="p">(</span><span class="n">a</span><span
                class="p">)</span>
  <span class="k">while</span> <span class="n">res</span> <span class="o">&lt;=</span> <span class="n">b</span><span
                class="p">:</span>
    <span class="k">yield</span> <span class="n">res</span>
    <span class="n">inc</span> <span class="n">res</span>

<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="mf">0</span><span class="p">...</span><span
                class="mi">5</span><span class="p">:</span>
  <span class="n">echo</span> <span class="n">i</span></code></pre>
    <pre><code class="language-console"><span class="gp">$</span> nim c -r operatoriterator.nim
<span class="go">0</span>
<span class="go">1</span>
<span class="go">2</span>
<span class="go">3</span>
<span class="go">4</span>
<span class="go">5</span></code></pre>

    <h2 id="inline-iterators">Inline Iterators</h2>
    <p>Inline iterators basically take the body of the for loop and inline it into the iterator. This means that they do
        not have any overhead from function calling, but if carelessly created may increase code size dramatically.</p>

    <pre><code class="language-nimrod"><span class="k">iterator</span> <span class="n">countTo</span><span
            class="p">(</span><span class="n">n</span><span class="p">:</span> <span class="kt">int</span><span
            class="p">):</span> <span class="kt">int</span> <span class="o">=</span>
  <span class="kd">var</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span>
  <span class="k">while</span> <span class="n">i</span> <span class="o">&lt;=</span> <span class="n">n</span><span
                class="p">:</span>
    <span class="k">yield</span> <span class="n">i</span>
    <span class="n">inc</span> <span class="n">i</span>

<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">countTo</span><span
                class="p">(</span><span class="mi">5</span><span class="p">):</span>
  <span class="n">echo</span> <span class="n">i</span></code></pre>
    <pre><code class="language-console"><span class="gp">$</span> nim c -r ./inline_iter.nim
<span class="go">0</span>
<span class="go">1</span>
<span class="go">2</span>
<span class="go">3</span>
<span class="go">4</span>
<span class="go">5</span></code></pre>

    <h2 id="closure-iterators">Closure Iterators</h2>
    <p>Closure iterators hold on to their state and can be resumed at any time. The <code>finished()</code> function can
        be used to check if there are any more elements available in the iterator, however raw iterator usage is
        unintuitive and difficult to get right.</p>

    <pre><code class="language-nimrod"><span class="k">proc </span><span class="nf">countTo</span><span
            class="p">(</span><span class="n">n</span><span class="p">:</span> <span class="kt">int</span><span
            class="p">):</span> <span class="k">iterator</span><span class="p">():</span> <span
            class="kt">int</span> <span class="o">=</span>
  <span class="k">return</span> <span class="k">iterator</span><span class="p">():</span> <span
                class="kt">int</span> <span class="o">=</span>
    <span class="kd">var</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span>
    <span class="k">while</span> <span class="n">i</span> <span class="o">&lt;=</span> <span class="n">n</span><span
                class="p">:</span>
      <span class="k">yield</span> <span class="n">i</span>
      <span class="n">inc</span> <span class="n">i</span>

<span class="k">let</span> <span class="n">countTo20</span> <span class="o">=</span> <span class="n">countTo</span><span
                class="p">(</span><span class="mi">20</span><span class="p">)</span>

<span class="n">echo</span> <span class="n">countTo20</span><span class="p">()</span>

<span class="kd">var</span> <span class="n">output</span> <span class="o">=</span> <span class="s">""</span>
<span class="c"># Raw iterator usage:</span>
<span class="k">while</span> <span class="kp">true</span><span class="p">:</span>
  <span class="c"># 1. grab an element</span>
  <span class="k">let</span> <span class="n">next</span> <span class="o">=</span> <span class="n">countTo20</span><span
                class="p">()</span>
  <span class="c"># 2. Is the element bogus? It's the end of the loop, discard it</span>
  <span class="k">if</span> <span class="n">finished</span><span class="p">(</span><span class="n">countTo20</span><span
                class="p">):</span>
    <span class="k">break</span>
  <span class="c"># 3. Loop body goes here:</span>
  <span class="n">output</span><span class="p">.</span><span class="n">add</span><span class="p">(</span><span
                class="o">$</span><span class="n">next</span> <span class="o">&amp;</span> <span
                class="s">" "</span><span class="p">)</span>

<span class="n">echo</span> <span class="n">output</span>

<span class="n">output</span> <span class="o">=</span> <span class="s">""</span>
<span class="k">let</span> <span class="n">countTo9</span> <span class="o">=</span> <span class="n">countTo</span><span
                class="p">(</span><span class="mi">9</span><span class="p">)</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">countTo9</span><span
                class="p">():</span>
  <span class="n">output</span><span class="p">.</span><span class="n">add</span><span class="p">(</span><span
                class="o">$</span><span class="n">i</span><span class="p">)</span>
<span class="n">echo</span> <span class="n">output</span></code></pre>
    <pre><code class="language-console"><span class="gp">$</span> nim c -r ./closure_iter.nim
<span class="go">0</span>
<span class="go">1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20</span>
<span class="go">0123456789</span></code></pre>

</article>

<div id=nextprev>
    <a class="text-icon disabled" href="https://please-enable-js/" id=arrow-prev>↽</a>
    <a class="text-icon disabled" href="https://please-enable-js/" id=arrow-next>⇁</a>
</div>

<footer>
    <li><a href="https://github.com/flaviut/nim-by-example">Contribute</a></li>
    <li
    ><a href="#" onclick="toggleDarkMode(); return false;">Toggle dark mode</a></li>

</footer>
</body>
</html>
